package com.kgc.gateway.filter;
import com.alibaba.fastjson.JSON;
import com.kgc.personcommon.util.JwtUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.*;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

//@Component
//public class JwtAuthGlobalFilter implements GlobalFilter, Ordered {
//
//    private Logger logger = LoggerFactory.getLogger(getClass());
//
//    private static final String HEADER = HttpHeaders.AUTHORIZATION;
//    private static final String PREFIX = "Bearer ";
//
//    @Autowired
//    private JwtUtil jwtUtil;
//
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        String path = exchange.getRequest().getURI().getPath();
//        logger.debug("Processing request: {}", path);
//        //检查请求路径，如果是 /api/auth/login 或 /public 开头的请求，直接放行。
//        if (path.contains("/user/login") || path.contains("/user/getCaptcha") || path.contains("/user/refresh") || path.contains("/user/logout") || path.contains("/public")) {
//            return chain.filter(exchange);
//        }
//        //获取头部信息
//        String header = exchange.getRequest().getHeaders().getFirst(HEADER);
//        //检查头部是否存在且格式正确，若不符合则返回 401 错误
//        if (!StringUtils.hasText(header) || !header.startsWith(PREFIX)) {
//            logger.warn("Missing or invalid Authorization header for path: {}", path);
//            return unauthorized(exchange, "Missing or invalid Authorization header");
//        }
//        //Token 解析与验证
//        String token = header.substring(PREFIX.length());
//        //使用 JwtUtil.validateToken(token) 验证 JWT 是否有效（签名、过期时间等）
//        if (!jwtUtil.validateToken(token)) {
//            logger.warn("Invalid or expired token for path: {}", path);
//            return unauthorized(exchange, "Token invalid or expired");
//        }
//        //从 JWT 中提取用户名和权限列表（角色）
//        String username = jwtUtil.getUsernameFromToken(token);
//        List<GrantedAuthority> roles = jwtUtil.getAuthFromToken(token).stream()
//                .map(SimpleGrantedAuthority::new)
//                .collect(Collectors.toList());
//        logger.debug("Authenticated user: {} with roles: {}", username, roles);
//
//        Date expirationDate = jwtUtil.getExpirationDate(token);
//        long timeLeft = expirationDate.getTime() - System.currentTimeMillis();
//
//
//        //创建 UsernamePasswordAuthenticationToken 认证对象，包含用户名和权限
//        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null, roles);
//        //将认证对象存入 ReactiveSecurityContextHolder，供下游微服务或过滤器使用
//        return chain.filter(exchange).subscriberContext(ctx -> ReactiveSecurityContextHolder.withAuthentication(auth).putAll(ctx));
//    }
//
//
//    //当认证失败时，返回 HTTP 401 状态码和 JSON 格式的错误信息
//    private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
//        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//        HttpHeaders headers = exchange.getResponse().getHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
//
//        // 添加 CORS 响应头
//        headers.add("Access-Control-Allow-Origin", "http://localhost:5173");
//        headers.add("Access-Control-Allow-Credentials", "true");
//
//        byte[] bytes = String.format("{\"status\":401,\"error\":\"%s\"}", msg)
//                .getBytes(StandardCharsets.UTF_8);
//        return exchange.getResponse()
//                .writeWith(Mono.just(exchange.getResponse()
//                        .bufferFactory()
//                        .wrap(bytes)));
//    }
//
//
//    // 保证在 Spring Security 的认证过滤器之前执行
//    @Override
//    public int getOrder() {
//        return Ordered.HIGHEST_PRECEDENCE;
//    }
//}
@Component
public class JwtAuthGlobalFilter implements GlobalFilter, Ordered {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final String HEADER = HttpHeaders.AUTHORIZATION;
    private static final String PREFIX = "Bearer ";

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        logger.debug("Processing request: {}", path);

        // 放行路径
        if (path.contains("/user/login") || path.contains("/user/getCaptcha") || path.contains("/user/refresh") || path.contains("/user/logout") || path.contains("/public")) {
            return chain.filter(exchange);
        }

        String header = exchange.getRequest().getHeaders().getFirst(HEADER);
        if (!StringUtils.hasText(header) || !header.startsWith(PREFIX)) {
            logger.warn("Missing or invalid Authorization header for path: {}", path);
            return unauthorized(exchange, "Missing or invalid Authorization header");
        }

        String token = header.substring(PREFIX.length());
        if (!jwtUtil.validateToken(token)) {
            logger.warn("Invalid or expired token for path: {}", path);
            return unauthorized(exchange, "Token invalid or expired");
        }

        String username = jwtUtil.getUsernameFromToken(token);

        // 从 Redis 获取权限
        String permsKey = "user:" + username + ":permissions";
        String json = redisTemplate.opsForValue().get(permsKey);
        if (json == null) {
            logger.warn("No permissions found in Redis for user: {}", username);
            return unauthorized(exchange, "权限信息过期，请重新登录");
        }

        List<String> apiPaths = JSON.parseArray(json, String.class);
        List<GrantedAuthority> roles = apiPaths.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());

        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null, roles);
        return chain.filter(exchange).subscriberContext(ctx -> ReactiveSecurityContextHolder.withAuthentication(auth).putAll(ctx));
    }

    private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        HttpHeaders headers = exchange.getResponse().getHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Access-Control-Allow-Origin", "http://localhost:5173");
        headers.add("Access-Control-Allow-Credentials", "true");

        byte[] bytes = String.format("{\"status\":401,\"error\":\"%s\"}", msg)
                .getBytes(StandardCharsets.UTF_8);
        return exchange.getResponse().writeWith(
                Mono.just(exchange.getResponse().bufferFactory().wrap(bytes))
        );
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}
